Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[APM] Critical path for a single trace #143735

Merged
merged 14 commits into from
Oct 27, 2022

Conversation

dgieselaar
Copy link
Member

@dgieselaar dgieselaar commented Oct 20, 2022

Part of #142370.

CleanShot 2022-10-27 at 19 41 31@2x

CleanShot 2022-10-27 at 19 41 45@2x

@dgieselaar dgieselaar added release_note:skip Skip the PR/issue when compiling release notes v8.5.0 labels Oct 20, 2022
(
normalizedChildStart >= scanTime ||
normalizedChildEnd < start ||
childEnd > scanTime
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderWert do you remember what the reasoning was here? I understand that a span cannot be on the critical path if it ends after its parent, because it implies that the parent doesn't care about it finishing, but this also eliminates spans that end after its sibling that was previously on the critical path. Which might be a valid reason, but wanted to clarify that with you.

Copy link
Member

@AlexanderWert AlexanderWert Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's take this one as an example:

image

The algorithm starts from the end with GET /api/order and we know that GET /api/order is on the CP. The spans Parse the document and Longtask are partially parallel to GET /api/order because they are not a parent of GET /api/order, started before GET /api/order, but DID NOT END before GET /api/order. This implies that the start of GET /api/oder is blocked by its parent rather one of the other two mentioned spans. As a consequence, the CP before GET /api/order lies on the parent orders and we can eliminate Parce the document and Longtask from the critical path.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that makes sense!

@dgieselaar dgieselaar marked this pull request as ready for review October 23, 2022 15:10
@dgieselaar dgieselaar requested a review from a team as a code owner October 23, 2022 15:10
@botelastic botelastic bot added the Team:APM All issues that need APM UI Team support label Oct 24, 2022
@elasticmachine
Copy link
Contributor

Pinging @elastic/apm-ui (Team:APM)

@dgieselaar dgieselaar requested review from a team as code owners October 24, 2022 08:14
Copy link
Member

@afharo afharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Core Changes LGTM

@cauemarcondes
Copy link
Contributor

cauemarcondes commented Oct 26, 2022

I think a Switch would look better in this case, since you are turning it on and off. You could even change the text to show/hide based on the status.

I also think using the tech preview icon instead of the text would look nicer. Especially because when I first look at this my first impression is that the entire waterfall is in tech preview,

cc: @boriskirov

@cauemarcondes
Copy link
Contributor

@dgieselaar is there any documentation we should point the users to? Is it clear what a critical path is for everyone?

Copy link
Contributor

@cauemarcondes cauemarcondes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few nits let me know what you think.

});
}

span({ spanName, spanType, spanSubtype, ...apmFields }: SpanParams) {
span(...options: [string, string] | [string, string, string] | [SpanParams]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very weird, why is it needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's basically method overloading, but in one signature. I think span(spanName) is often good enough and more concise than span({ spanName: ... }). I previously discussed this with @sqren when he changed it, and IIRC(?) we decided I would add back the original method when I would have time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it makes the signature simpler but I'd rather be without the extra complexity in synthtrace. But I don't feel strongly for it either way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'll take that back. I don't think the signature improved except for transaction() with a single arg.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the signature is more complicated but not less easy to use, which is my goal. Like you know, I disagree about span({...}) and transaction({...}) being the better interface. I do we think should add more defaults for span() though, IMHO span(spanName) is good enough too, we can default to custom/custom for span type and subtype.

Comment on lines +23 to +31
export function service(name: string, environment: string, agentName: string): Service;

export function service(options: { name: string; environment: string; agentName: string }): Service;

export function service(
...args: [{ name: string; environment: string; agentName: string }] | [string, string, string]
) {
const [serviceName, environment, agentName] =
args.length === 1 ? [args[0].name, args[0].environment, args[0].agentName] : args;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this overcomplicate this a bit? Is it really necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above.

Comment on lines +318 to +323
description: i18n.translate('xpack.observability.enableCriticalPathDescription', {
defaultMessage: '{technicalPreviewLabel} Optionally display the critical path of a trace.',
values: {
technicalPreviewLabel: `<em>[${technicalPreviewLabel}]</em>`,
},
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boriskirov we're showing a link where users can give feedback for tech preview features, isn't there a link for this as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderWert how do you feel about this?

* 2.0.
*/

import type { IWaterfallSpanOrTransaction } from '../../public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_helpers/waterfall_helpers';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this look odd a common file importing stuff from a public component? Can you move the typing definitions of the waterfall to a common folder and use it here and adjust the imports? That's already a starting point to refactor the waterfall, we discussed about moving some of the logic to the server a couple of weeks ago.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a type-only import which I think is usually fine. I get your point, but I think there's also a lot of value of co-locating types with the code that uses them (the most).

// the critical path, but we only want one to contribute.
// - The span/tx ends before the start of the initial scan period.
// - The span ends _after_ the current scan time.
(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you remove this extra (?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'm actually surprised ESLint doesn't remove this. Maybe it adds it automatically because of the comment, I'll look into it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ESLint adds it automatically :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you move the comments up it'll look nicer. but it's up to you.

import { enableCriticalPath } from '@kbn/observability-plugin/common';
import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_context';

export function useCriticalPathEnabledSetting() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export function useCriticalPathEnabledSetting() {
export function useCriticalPathSetting() {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to distinguish between whether the feature is enabled and whether it is toggled on in the current view. Not sure if this is the best name but it's better than useCriticalPathSetting IMO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change it to align the settings name as discussed below I think it'll be fine: useCriticalPathFeatureEnabledSetting

Comment on lines +192 to +196
defaults: {
query: {
showCriticalPath: '',
},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it necessary if you'll use the value defined in the settings?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some cases we cannot type-check links (e.g. when linking from outside the app), this is to handle those cases.

Comment on lines +107 to +114
const criticalPath = showCriticalPath
? getCriticalPath(waterfall)
: undefined;

const criticalPathSegmentsById = groupBy(
criticalPath?.segments,
(segment) => segment.item.id
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's important to wrap it inside a useMemo so it won't recalculate on every render?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be fast enough. There will only be a handful of segments in most cases.

onShowCriticalPathChange={(nextShowCriticalPath) => {
push(history, {
query: {
showCriticalPath: nextShowCriticalPath ? 'true' : 'false',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use toString instead?

Suggested change
showCriticalPath: nextShowCriticalPath ? 'true' : 'false',
showCriticalPath: nextShowCriticalPath.toString(),

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point, but I think I have a slight preference for being explicit here.

<Waterfall waterfallItemId={waterfallItemId} waterfall={waterfall} />
</div>
<EuiFlexGroup direction="column">
{isCriticalPathEnabled ? (
Copy link
Contributor

@cauemarcondes cauemarcondes Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name of the setting and the props are a bit confusing. I think the other way around would make more sense.

Change the settings to showCriticalPath and change the props to enableCriticalPath.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about swapping them, I think I'll change it to isCriticalPathFeatureEnabled or maybe isCriticalPathFeatureAvailable. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think isCriticalPathFeatureEnabled is better.

@dgieselaar
Copy link
Member Author

@cauemarcondes I think I got most of it, mind having another look?

Copy link
Contributor

@cauemarcondes cauemarcondes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

// the critical path, but we only want one to contribute.
// - The span/tx ends before the start of the initial scan period.
// - The span ends _after_ the current scan time.
(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you move the comments up it'll look nicer. but it's up to you.

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
apm 1336 1338 +2

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/apm-synthtrace 74 76 +2
observability 536 546 +10
total +12

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
apm 3.1MB 3.1MB +3.4KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
observability 68.0KB 68.2KB +127.0B
Unknown metric groups

API count

id before after diff
@kbn/apm-synthtrace 74 76 +2
observability 540 550 +10
total +12

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@dgieselaar dgieselaar merged commit 4bd8693 into elastic:main Oct 27, 2022
@dgieselaar dgieselaar deleted the critical-path-preview branch October 27, 2022 19:33
@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.5 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 143735

Questions ?

Please refer to the Backport tool documentation

jloleysens added a commit to jloleysens/kibana that referenced this pull request Oct 27, 2022
* main: (24 commits)
  [Files] Add file upload to file picker (elastic#143969)
  [Security solution] Guided onboarding, alerts & cases (elastic#143598)
  [APM] Critical path for a single trace (elastic#143735)
  skip failing test suite (elastic#143933)
  [Fleet] Update GH Projects automation (elastic#144123)
  [APM] Performance fix for 'cardinality' telemetry task (elastic#144061)
  [Enterprise Search] Attach ML Inference Pipeline - Pipeline re-use (elastic#143979)
  [8.5][DOCS] Add support for differential logs (elastic#143242)
  Bump nwsapi from v2.2.0 to v2.2.2 (elastic#144001)
  [APM] Add waterfall to dependency operations (elastic#143257)
  [Shared UX] Add deprecation message to kibana react Markdown (elastic#143766)
  [Security Solution][Endpoint] Adds RBAC API checks for Blocklist (elastic#144047)
  Improve `needs-team` auto labeling regex (elastic#143787)
  [Reporting/CSV Export] _id field can not be formatted (elastic#143807)
  Adds SavedObjectsWarning to analytics results pages. (elastic#144109)
  Bump chromedriver to 107 (elastic#144073)
  Update cypress (elastic#143755)
  [Maps] nest security layers in layer group (elastic#144055)
  [Lens][Agg based Heatmap] Navigate to Lens Agg based Heatmap. (elastic#143820)
  Added support of saved search (elastic#144095)
  ...
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Oct 28, 2022
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add the label auto-backport or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 143735 locally

1 similar comment
@kibanamachine
Copy link
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add the label auto-backport or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 143735 locally

.timestamp(1)
.duration(100)
.children(
service.span('foo', 'external', 'db').duration(100).timestamp(1)
Copy link
Member

@sorenlouv sorenlouv Oct 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think this reads worse than before. I'm not sure what either of those arguments are.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, it's clear to me. I realise I'm biased as the author but I think you're also exaggerating a little bit here :).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, it's clear to me

How many on the team do you think will know that "foo" is span.name, "external" is span.type and "db" is span.subtype?

If it's more than half I'll shut up. We should do a pop quiz and settle this ;)

@dgieselaar dgieselaar removed the v8.5.0 label Nov 1, 2022
@kibanamachine kibanamachine added backport:skip This commit does not require backporting and removed backport missing Added to PRs automatically when the are determined to be missing a backport. labels Nov 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:APM All issues that need APM UI Team support v8.6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants